package com.slz3.business.frame.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

/**
 * 转换公共方法
 *
 * @Author QuMingYang
 * @Date 2018/9/13
 * @Version V1.0.0
 * @Update 更新说明
 */
public class ConvertUtil {

    private ConvertUtil() {
    }

    /**
     * 将t1和k1的公有字段转化为k1对象,注意：此方法会舍弃掉非公有字段
     *
     * @param t1  原始对象
     * @param k1  转换后对象
     * @param <T> 原始类型
     * @param <K> 转换后类型
     * @return 转换后对象
     * @throws IllegalArgumentException 转换异常
     */

    public static <T, K> K objToObj(T t1, Class<K> k1) {
        try {
            ObjectMapper mapper = getObjectMapper();
            String json = getObjToStr(t1, mapper);
            return mapper.readValue(json, k1);
        } catch (IOException e) {
            throw new IllegalArgumentException("objToObj对象转换异常", e);
        }
    }

    /**
     * 将t1转为map
     *
     * @param <T> 原始类型
     * @param t1  原始对象
     * @return 转换后对象
     * @throws IllegalArgumentException 转换异常
     */

    public static <T> Map<String, Object> objToMap(T t1) {
        try {
            ObjectMapper mapper = getObjectMapper();
            String json = getObjToStr(t1, mapper);
            return mapper.readValue(json, new TypeReference<Map<String, Object>>() {
            });
        } catch (IOException e) {
            throw new IllegalArgumentException("objToMap对象转换异常", e);
        }
    }

    /**
     * 将t1转为map
     *
     * @param <T> 原始类型
     * @param t1  原始对象
     * @return 转换后对象
     * @throws IllegalArgumentException 转换异常
     */

    public static <T> T mapToObj(Map<Object, Object> map, Class<T> t1) {
        try {
            ObjectMapper mapper = getObjectMapper();
            String json = getObjToStr(map, mapper);
            return mapper.readValue(json, t1);
        } catch (IOException e) {
            throw new IllegalArgumentException("mapToObj对象转换异常", e);
        }
    }

    /**
     * 将t1转为list<k1>
     *
     * @param <T> 原始类型
     * @param t1  原始对象
     * @return 转换后对象
     * @throws IllegalArgumentException 转换异常
     */

    public static <T, K> List<K> objToList(T t1, Class<K> k1) {
        try {
            ObjectMapper mapper = getObjectMapper();
            String json = getObjToStr(t1, mapper);
            JavaType javaType = getCollectionType(mapper, ArrayList.class, k1);
            return mapper.readValue(json, javaType);
        } catch (IOException e) {
            throw new IllegalArgumentException("objToList对象转换异常", e);
        }
    }

    /**
     * @param collectionClass 集合类
     * @param elementClasses  集合元素类
     * @return javaType
     */
    private static JavaType getCollectionType(ObjectMapper mapper, Class<?> collectionClass, Class<?>... elementClasses) {
        return mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
    }


    /**
     * 将List<T> 转为List<K> ,注意：此方法会舍弃掉非公有字段
     *
     * @param t1  List<T>
     * @param k1  转换后对象
     * @param <T> 原始类型
     * @param <K> 转换后类型
     * @return 转换后对象
     * @throws IllegalArgumentException 转换异常
     */
    public static <T, K> List<K> listObjToListObj(List<T> t1, Class<K> k1) {
        try {
            ObjectMapper mapper = getObjectMapper();
            String json = mapper.writeValueAsString(t1);
            JavaType javaType = getCollectionType(mapper, ArrayList.class, k1);
            return mapper.readValue(json, javaType);
        } catch (IOException e) {
            throw new IllegalArgumentException("listObjToListObj对象转换异常" + k1, e);
        }
    }


    /**
     * 对象转字符串
     *
     * @param t1 t1
     * @return 转换后字符串
     */
    public static <T> String getObjToStr(T t1) {
        ObjectMapper mapper = getObjectMapper();
        String json;
        try {
            if (!(t1 instanceof String)) {
                json = mapper.writeValueAsString(t1);
            } else {
                json = String.valueOf(t1);
            }
        } catch (IOException e) {
            throw new IllegalArgumentException("getObjToStr对象转换异常" + t1, e);
        }
        return json;
    }

    /**
     * 对象转字符串
     *
     * @param t1     t1
     * @param mapper ObjectMapper
     * @return 转换后字符串
     */
    private static <T> String getObjToStr(T t1, ObjectMapper mapper) throws JsonProcessingException {
        String json;
        if (!(t1 instanceof String)) {
            json = mapper.writeValueAsString(t1);
        } else {
            json = String.valueOf(t1);
        }
        return json;
    }

    /**
     * 嵌套对象转换
     *
     * @param obj 转换对象
     * @param t1  转换后类型
     * @return 转换后字符串
     */
    public static <T> T objToNestingObj(Object obj, TypeReference<T> t1) {
        try {
            ObjectMapper mapper = getObjectMapper();
            String json = getObjToStr(obj, mapper);
            return mapper.readValue(json, t1);
        } catch (IOException e) {
            throw new IllegalArgumentException("ObjToNestingObj对象转换异常", e);
        }
    }

    /**
     * 创建mapper
     *
     * @return ObjectMapper
     */
    private static ObjectMapper getObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        mapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        return mapper;
    }

    /**
     * @param obj 规范强转
     * @param <T> 强转类型
     * @return 转换结果
     */
    @SuppressWarnings("unchecked")
    private static <T> T cast(Object obj) {
        return (T) obj;
    }
}
